﻿function AzureStorageBlobsApi(credentials, channel) {

    var self = this;

    function getBaseUrl() {
        return credentials.getBlobsUrl();
    }

    function onError(request) {
        var responeText = request.responseText;
    }

    function execute(request, options) {
        request.sign(credentials);

        return channel.send(request, function (data, req) {
            if (options && options.success) {
                if (request.acceptBase64) {
                    data = new Base64().decode(data);
                }
                options.success(data, req);
            }
        }, function (data, req) {
            onError(req);
            var action = 'notify';
            if (options && options.error) action = options.error(data, req);
            if (action == 'notify') {
                notificationArea.showError(req.statusText);
            }
        }, function () {
        });
    }

    function getUri(relPath) {
        relPath = relPath || '';
        return new Uri().parse(getBaseUrl() + relPath);
    }
    
    var requests = {
        createContainer: function (options) {
            var container = options.container;
            var request = new AzureRequest();
            request.verb = 'PUT';
            request.uri = getUri(container);
            request.headers['Content-Length'] = '0';
            request.signatureType = 'SharedKey';
            request.addQuery('restype', 'container');
            return request;
        },
        listContainers: function () {
            var request = new AzureRequest();
            request.verb = 'GET';
            request.uri = getUri();
            request.signatureType = 'SharedKey';
            request.addQuery('comp', 'list');
            request.addQuery('timeout', 90);
            request.addQuery('include', 'metadata');
            return request;
        },
        leaseContainer: function (options) {
            var container = options.container;

            var request = new AzureRequest();
            request.verb = 'PUT';
            request.uri = getUri(container);
            request.headers['Content-Length'] = '0';
            request.headers['x-ms-version'] = '2012-02-12';

            if (options.leaseId) {
                request.headers['x-ms-lease-id'] = options.leaseId;
            }
            if (options.action) {
                request.headers['x-ms-lease-action'] = options.action;
            }
            if (options.breakPeriod) {
                request.headers['x-ms-lease-break-period'] = options.breakPeriod;
            }
            if (options.duration) {
                request.headers['x-ms-lease-duration'] = options.duration;
            }
            request.addQuery('comp', 'lease');
            request.addQuery('restype', 'container');
            request.signatureType = 'SharedKey';
            return request;
        },
        deleteContainer: function (options) {
            var container = options.container;
            var request = new AzureRequest();
            request.verb = 'DELETE';
            request.uri = getUri(container);
            request.signatureType = 'SharedKey';
            request.addQuery('restype', 'container');
            return request;
        },
        listBlobs: function (options) {
            var container = options.container;

            var request = new AzureRequest();
            request.verb = 'GET';
            request.uri = getUri(container);
            request.signatureType = 'SharedKey';
            request.addQuery('restype', 'container');
            request.addQuery('comp', 'list');
            request.addQuery('include', 'metadata');
            if (options.prefix) {
                request.addQuery('prefix', options.prefix);
            }
            return request;
        },
        getBlob: function (options) {
            var container = options.container;
            var name = options.blob;

            var request = new AzureRequest();
            request.verb = 'GET';
            request.uri = getUri(container + '/' + name);
            if (options.range) {
                var range = options.range;
                request.headers['x-ms-range'] = 'bytes=' + range.min + '-' + range.max;
            }
            request.acceptBase64 = true;
            request.signatureType = 'SharedKey';
            return request;
        },
        setBlobProperties: function (options) {
            var container = options.container;
            var name = options.blob;

            var request = new AzureRequest();
            request.verb = 'PUT';
            request.uri = getUri(container + '/' + name);
            request.addQuery('comp', 'properties');
            request.headers['Content-Length'] = '0';

            var props = options.properties;
            if (props.cacheControl) {
                request.headers['x-ms-blob-cache-control'] = props.cacheControl;
            }
            if (props.contentEncoding) {
                request.headers['x-ms-blob-content-encoding'] = props.contentEncoding;
            }
            if (props.contentLanguage) {
                request.headers['x-ms-blob-content-language'] = props.contentLanguage;
            }
            if (props.contentType) {
                request.headers['x-ms-blob-content-type'] = props.contentType;
            }
            if (props.contentMD5) {
                request.headers['x-ms-blob-content-md5'] = props.contentMD5;
            }
            if (props.contentLength) {
                request.headers['x-ms-blob-content-length'] = props.contentLength;
            }
            request.signatureType = 'SharedKey';
            return request;
        },
        putPage: function (options) {
            var container = options.container;
            var name = options.blob;
            var data = options.data;

            var request = new AzureRequest();
            request.verb = 'PUT';
            request.uri = getUri(container + '/' + name);
            if (options.range) {
                var range = options.range;
                request.headers['x-ms-range'] = 'bytes=' + range.min + '-' + range.max;
            }
            request.headers['Content-Length'] = data.length;
            request.headers['Content-Type'] = 'application/octet-stream';
            request.headers['x-ms-page-write'] = 'update';
            request.addQuery('comp', 'page');
            request.data = data;
            request.signatureType = 'SharedKey';
            return request;
        },
        putBlob: function (options) {
            var container = options.container;
            var name = options.blob;
            var type = options.type;

            var request = new AzureRequest();
            request.verb = 'PUT';
            request.uri = getUri(container + '/' + name);
            request.headers['x-ms-blob-type'] = type;
            switch (type) {
                case 'PageBlob':
                    request.headers['x-ms-blob-content-length'] = options.size;
                    request.headers['Content-Length'] = '0';
                    break;
                case 'BlockBlob':
                    var content = options.content;
                    var contentBytes = new UTF8().getBytes(content);
                    request.headers['Content-Length'] = contentBytes.length;
                    request.data = content;
                    break;
            }
            request.signatureType = 'SharedKey';
            return request;
        },
        leaseBlob: function (options) {
            var container = options.container;
            var name = options.blob;

            var request = new AzureRequest();
            request.verb = 'PUT';
            request.uri = getUri(container + '/' + name);;
            request.headers['Content-Length'] = '0';
            request.version = '2012-02-12';
            if (options.leaseId) {
                request.headers['x-ms-lease-id'] = options.leaseId;
            }
            if (options.action) {
                request.headers['x-ms-lease-action'] = options.action;
            }
            if (options.breakPeriod) {
                request.headers['x-ms-lease-break-period'] = options.breakPeriod;
            }
            if (options.duration) {
                request.headers['x-ms-lease-duration'] = options.duration;
            }
            request.addQuery('comp', 'lease');
            request.signatureType = 'SharedKey';
            return request;
        },
        setBlobMetadata: function (options) {
            var container = options.container;
            var name = options.blob;

            var request = new AzureRequest();
            request.verb = 'PUT';
            request.uri = getUri(container + '/' + name);;
            request.headers['Content-Length'] = '0';
            request.version = '2012-02-12';
            request.addQuery('comp', 'metadata');
            if (options.leaseId) {
                request.headers['x-ms-lease-id'] = options.leaseId;
            }
            if (options.metadata) {
                for (var i = 0; i < options.metadata.length; i++) {
                    var row = options.metadata[i];
                    request.headers['x-ms-meta-' + row.name] = row.value;
                }
            }
            request.signatureType = 'SharedKey';
            return request;
        },
        setContainerMetadata: function (options) {
            var container = options.container;

            var request = new AzureRequest();
            request.verb = 'PUT';
            request.uri = getUri(container);
            request.headers['Content-Length'] = '0';
            request.version = '2012-02-12';
            request.addQuery('restype', 'container');
            request.addQuery('comp', 'metadata');
            if (options.leaseId) {
                request.headers['x-ms-lease-id'] = options.leaseId;
            }
            if (options.metadata) {
                for (var i = 0; i < options.metadata.length; i++) {
                    var row = options.metadata[i];
                    request.headers['x-ms-meta-' + row.name] = row.value;
                }
            }
            request.signatureType = 'SharedKey';
            return request;
        },
        deleteBlob: function (options) {
            var container = options.container;
            var name = options.blob;

            var request = new AzureRequest();
            request.verb = 'DELETE';
            request.uri = getUri(container + '/' + name);
            request.signatureType = 'SharedKey';
            return request;
        },
        getServiceProperties: function () {
            var request = new AzureRequest();
            request.verb = 'GET';
            request.uri = getUri();
            request.signatureType = 'SharedKey';
            request.addQuery('restype', 'service');
            request.addQuery('comp', 'properties');
            return request;
        },
        setServiceProperties: function (options) {
            var content = options.content;
            var contentBytes = new UTF8().getBytes(content);
            
            var request = new AzureRequest();
            request.verb = 'PUT';
            request.uri = getUri();
            
            request.headers['Content-Type'] = 'application/xml';
            request.headers['Content-Length'] = contentBytes.length;
            request.data = options.content;

            request.signatureType = 'SharedKey';
            request.addQuery('restype', 'service');
            request.addQuery('comp', 'properties');
            return request;
        }
    };

    function listContainers(options) {
        var request = requests.listContainers(options);
        execute(request, options);
    }

    function createContainer(options) {
        var request = requests.createContainer(options);
        execute(request, options);
    }

    function leaseContainer(options) {
        var request = requests.leaseContainer(options);
        execute(request, options);
    }

    function removeContainer(options) {
        var request = requests.deleteContainer(options);
        execute(request, options);
    }

    function listBlobs(options) {
        var request = requests.listBlobs(options);
        execute(request, options);
    }

    function getBlob(options) {
        var request = requests.getBlob(options);
        execute(request, options);
    }

    function setBlobMetadata(options) {
        var request = requests.setBlobMetadata(options);
        execute(request, options);
    }

    function setBlobProperties(options) {
        var request = requests.setBlobProperties(options);
        execute(request, options);
    }

    function setContainerMetadata(options) {
        var request = requests.setContainerMetadata(options);
        execute(request, options);
    }

    function deleteBlob(options) {
        var request = requests.deleteBlob(options);
        execute(request, options);
    }

    function putBlob(options) {
        var request = requests.putBlob(options);
        execute(request, options);
    }

    function putPage(options) {
        var request = requests.putPage(options);
        execute(request, options);
    }

    function leaseBlob(options) {
        var request = requests.leaseBlob(options);
        execute(request, options);
    }

    function getDownloadBlobUrl(options) {
        var request = requests.getBlob(options);

        var name = options.blob;
        var downloadName = name;
        if (downloadName.indexOf('.') < 0) {
            downloadName += '.bin';
        }

        request.downloadName = downloadName;
        request.sign(credentials);
        return channel.getDownloadUrl(request);
    }

    function downloadBlob(options) {
        var container = options.container;
        var name = options.blob;

        var downloadName = name;
        if (downloadName.indexOf('.') < 0) {
            downloadName += '.bin';
        }

        var request = new AzureRequest();
        request.verb = 'GET';
        request.uri = getUri(container + '/' + name);
        request.downloadName = downloadName;
        request.signatureType = 'SharedKey';
        execute(request, options);
    }
    
    function getServiceProperties(options) {
        var request = requests.getServiceProperties(options);
        execute(request, options);
    }

    function setServiceProperties(options) {
        var request = requests.setServiceProperties(options);
        execute(request, options);
    }
    
    self.requests = requests;
    self.listContainers = listContainers;
    self.createContainer = createContainer;
    self.leaseContainer = leaseContainer;

    self.removeContainer = removeContainer;
    self.listBlobs = listBlobs;
    self.getBlob = getBlob;
    self.setBlobMetadata = setBlobMetadata;
    self.setContainerMetadata = setContainerMetadata;
    self.setBlobProperties = setBlobProperties;
    self.deleteBlob = deleteBlob;
    self.putBlob = putBlob;
    self.putPage = putPage;

    self.leaseBlob = leaseBlob;
    self.downloadBlob = downloadBlob;
    self.getDownloadBlobUrl = getDownloadBlobUrl;
    
    self.getServiceProperties = getServiceProperties;
    self.setServiceProperties = setServiceProperties;

}
